# coding:utf-8

from . import api
from flask import g, current_app, jsonify, request, session
from ihome.utils.response_code import RET
from ihome.models import Area, House, Facility, HouseImage, Order
from ihome import db, redis_store
from ihome.utils.commons import require_login
from ihome.utils.image_storage import storage
from ihome.utils.constains import QINIU_DOMAIN, SLIDER_PAGE, SLIDER_PAGE_IN_REDIS, HOUSE_DETAIL_IN_REDIS,SEARCH_RESULT, PAGE_SIZE
import json
from datetime import datetime


@api.route("/houses/info", methods=["POST"])
@require_login
def save_house_info():

    # 获取数据
    user_id = g.user_id
    house_data = request.get_json()

    title = house_data.get("title")  # 房屋名称标题
    price = house_data.get("price")  # 房屋单价
    area_id = house_data.get("area_id")  # 房屋所属城区的编号
    address = house_data.get("address")  # 房屋地址
    room_count = house_data.get("room_count")  # 房屋包含的房间数目
    acreage = house_data.get("acreage")  # 房屋面积
    unit = house_data.get("unit")  # 房屋布局（几室几厅)
    capacity = house_data.get("capacity")  # 房屋容纳人数
    beds = house_data.get("beds")  # 房屋卧床数目
    deposit = house_data.get("deposit")  # 押金
    min_days = house_data.get("min_days")  # 最小入住天数
    max_days = house_data.get("max_days")  # 最大入住天数

    # 校验参数
    if not all([title, price, area_id, address, room_count, acreage, unit, capacity, beds, deposit, min_days, max_days]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")

    # 判断金额是否正确
    try:
        price = int(float(price) * 100)
        deposit = int(float(deposit) * 100)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 判断城区id是否存在
    try:
        area = Area.query.get(area_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    if area is None:
        return jsonify(errno=RET.NODATA, errmsg="城区信息有误")

    # 保存房屋信息
    house = House(
        user_id=user_id,
        area_id=area_id,
        title=title,
        price=price,
        address=address,
        room_count=room_count,
        acreage=acreage,
        unit=unit,
        capacity=capacity,
        beds=beds,
        deposit=deposit,
        min_days=min_days,
        max_days=max_days
    )

    # 处理房屋的设施信息
    facility_ids = house_data.get("facility")

    # 如果用户勾选了设施信息，再保存数据库
    if facility_ids:
        try:
            facilities = Facility.query.filter(Facility.id.in_(facility_ids)).all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据库异常")

        if facilities:
            # 表示有合法的设施数据
            # 保存设施数据
            house.facilities = facilities

    try:
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存数据失败")

    # 保存数据成功
    return jsonify(errno=RET.OK, errmsg="OK", data={"house_id": house.id})


@api.route("/houses/image", methods=["POST"])
@require_login
def save_house_image():
    """保存房屋的图片
    参数 图片 房屋的id
    """
    image_file = request.files.get("house_image")
    house_id = request.form.get("house_id")

    if not all([image_file, house_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 判断house_id正确性
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    if house is None:  # if not house:
        return jsonify(errno=RET.NODATA, errmsg="房屋不存在")

    image_data = image_file.read()
    # 保存图片到七牛中
    try:
        file_name = storage(image_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg="保存图片失败")

    # 保存图片信息到数据库中
    house_image = HouseImage(house_id=house_id, url=file_name)
    db.session.add(house_image)

    # 处理房屋的主图片
    if not house.index_image_url:
        house.index_image_url = file_name
        db.session.add(house)

    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存图片数据异常")

    image_url = QINIU_DOMAIN + file_name

    return jsonify(errno=RET.OK, errmsg="OK", data={"image_url": image_url})


@api.route('/get_house_index', methods=["GET"])
def get_house_index():
    """获取主页中轮播图片"""
    try:
        ret = redis_store.get('home_page_data')
    except Exception as e:
        current_app.logger.error(e)
        ret = None
    if ret:
        return '{"errno": 0, "errmsg": "ok", "data": %s}' % ret, 200, {"Content-Type": "application/json"}
    else:
        try:
            # 如果redis中没有缓存就在数据库中查询
            houses = House.query.order_by(House.order_count.desc()).limit(SLIDER_PAGE)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")
        img_list = []

        for house in houses:
            if not house.index_image_url:
                continue
            img_list.append(house.house_to_dict())

        json_house = json.dumps(img_list)
        try:
            redis_store.setex('home_page_data', SLIDER_PAGE_IN_REDIS, json_house)
        except Exception as e:
            current_app.logger.error(e)

        return '{"errno": 0, "errmsg": "ok", "data": %s}' % json_house, 200, {"Content-Type": "application/json"}


@api.route('/house/<int:house_id>', methods=["GET"])
def get_house_detail(house_id):
    # 获取用户的id，防止房东刷单
    user_id = session.get('user_id', -1)

    if not house_id:
        return jsonify(errno=RET.PARAMERR, errmsg="参数缺失")

    try:
        ret = redis_store.get("house_info_%s" % house_id)
    except Exception as e:
        current_app.logger.error(e)
        ret = None
    if ret:
        return '{"errno": 0, "errmsg": "ok", "data": {"user_id": %s, "house": %s}}' % (user_id, ret), 200, {"Content-Type": "application/json"}
    else:
        try:
            house = House.query.get(house_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")

        if not house:
            return jsonify(RET.NODATA, errmsg="数据为空")
        # 将房屋数据转化为字典
        house_info = house.to_full_dict()
        json_house = json.dumps(house_info)

        # 保存到redis中
        try:
            redis_store.setex("house_info_%s"  % house_id, HOUSE_DETAIL_IN_REDIS, json_house)
        except Exception as e:
            current_app.logger.error(e)

        return '{"errno": 0, "errmsg": "ok", "data": {"user_id": %s, "house": %s}}' % (user_id, json_house), 200, {"Content-Type": "application/json"}


@api.route('/house')
def get_house_list():
    start_time = request.args.get('sd', '')
    end_time = request.args.get('ed', '')
    sort_key = request.args.get('sk', 'new')
    area_id = request.args.get('aid', '')
    page = request.args.get('p')

    try:
        if start_time:
            start_time = datetime.strptime(start_time, '%Y-%m-%s')
        if end_time:
            end_time = datetime.strptime(end_time, '%Y-%m-%s')
        if end_time and start_time:
            assert end_time >= start_time
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="日期参数错误")
    # 处理区域参数
    if area_id:
        try:
            area = Area.query.get(area_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR, errmsg="区域参数有误")
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    try:
        redis_key = "house_%s_%s_%s_%s" % (start_time, end_time, area_id, sort_key)
        resp_json = redis_store.hget(redis_key, page)
    except Exception as e:
        current_app.logger.error(e)
    else:
        if resp_json:
            print ('hit')
            return resp_json, 200, {"Content-Type": "application/json"}

    # 过滤条件列表
    filter_params = []
    house_query = None
    # 填充过滤参数
    # 过滤时间冲突
    conflict_orders = None
    conflict_house_id = None
    try:
        if start_time and end_time:
            conflict_orders = Order.query.filter(Order.begin_date <= end_time, Order.end_date >= start_time).all()
        if start_time:
            conflict_orders = Order.query.filter(Order.end_date >= start_time).all()
        if end_time:
            conflict_orders = Order.query.filter(Order.begin_date <= end_time).all()

        if conflict_orders:
            conflict_house_id = [order.house_id for order in conflict_orders]
        if conflict_house_id:
            filter_params.append(House.id.notin_(conflict_house_id))
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库错误")
    # 区域条件
    if area_id:
        filter_params.append(House.area_id == area_id)
    # 排序条件
    try:
        if sort_key == 'price-inc':
            house_query = House.query.filter(*filter_params).order_by(House.price.asc())
        if sort_key == 'price-des':
            house_query = House.query.filter(*filter_params).order_by(House.price.desc())
        if sort_key == 'booking':
            house_query = House.query.filter(*filter_params).order_by(House.order_count.desc())
        else:
            house_query = House.query.filter(*filter_params).order_by(House.create_time.desc())
    except Exception as e:
        current_app.logger.error(e)
    # 处理分页

    page_obj = house_query.paginate(page=page, per_page=PAGE_SIZE, error_out=False)

    # 获取页面数据
    house_li = page_obj.items
    houses = []
    for house in house_li:
        houses.append(house.to_full_dict())
    total_page = page_obj.pages
    resp_dict = dict(errno=RET.OK, errmsg="OK", data={"total_page": total_page, 'houses': houses, 'current_page': page})
    resp_json = json.dumps(resp_dict)
    if page <= total_page:
        redis_key = "house_%s_%s_%s_%s" % (start_time, end_time, area_id, sort_key)
        try:
            # redis_store.hset(redis_key, page, resp_json)
            # redis_store.expire(redis_key, SEARCH_RESULT)
        # 创建管道对象一次执行多次，防止操作终端引起的永久存储
            pipeline = redis_store.pipeline()
            # 开启多个记录
            pipeline.multi()
            pipeline.hset(redis_key, page, resp_json)
            pipeline.expire(redis_key, SEARCH_RESULT)
            pipeline.execute()
        except Exception as e:
            current_app.logger.error(e)
    return resp_json, 200, {"Content-Type":"application/json"}





